#pragma once

#include "Util.hpp"

#include <string>
#include <vector>
#include <sstream>
#include <unordered_map>

const static string SEP = "\r\n";
const static string webRoot = "./webRoot";
const static string defaultHomePage = "/index.html"; // 默认页面
const static string errPage_404 = "/err404.html";    // 404页面

class Request
{
public:
    Request()
    {}

    // 反序列化
    bool Deserialization(const std::string& url)
    {
        // 根据 url 进行解析
        int n = 0;
        std::vector<std::string> vstr;
        while(true)
        {
            std::string line;
            n = Util::ReadLine(url, n, SEP, &line) + SEP.size();

            if(line.empty())
                break;

            vstr.push_back(line);
        }

        // 解析请求行
        ParseFirstLine(vstr[0]);

        // 解析报头部分
        ParseHeaderLine(vstr);

        // 读取并解析有效载荷（可能没有）
        Util::ReadLine(url, n, SEP, &_body);

        return true;
    }

    // 解析请求行
    bool ParseFirstLine(const std::string& str)
    {
        // 读取方法、资源路径、协议版本
        std::stringstream ss(str);
        ss >> _method >> _path >> _version;

        // 解析出后缀
        if(_path == "/")
            _path = defaultHomePage;

        // 实际路径 = web根目录 + 请求资源路径
        int pos = _path.find_last_of(".");
        if(pos == std::string::npos)
            _suffix = ".html";
        else
            _suffix = _path.substr(pos);
        _path = webRoot + _path;

        return true;
    }
  
    // 解析报头部分
    bool ParseHeaderLine(const std::vector<std::string>& vstr)
    {
        for(int i = 1; i < vstr.size(); i++)
        {
            const std::string& str = vstr[i];

            int pos = str.find(':');
            std::string key = str.substr(0, pos);
            std::string value = str.substr(pos + 2);

            _headers[key] = value;
        }

        return true;
    }
  
    ~Request()
    {}

public:
    std::string _method; // 请求方法
    std::string _path;   // 资源路径
    std::string _suffix; // 资源后缀
    std::string _version;// 协议版本
    std::unordered_map<std::string, std::string> _headers; // 请求报头
    std::string _body;   // 有效载荷
};

class Response
{
public:
    Response()
    {}

    // class Session
    // {
    // public:
    //     Session(const std::string& id, const std::string& passwd)
    //         :_id(id), _passwd(passwd)
    //     {}

    //     ~Session()
    //     {}

    // public:
    //     std::string _id;
    //     std::string _passwd;
    //     std::string _login_time; // 登录时间
    //     std::string _status;     // 用户状态
    // };

    // // 首次登录
    // int Login(const Request& req)
    // {
    //     // 获取 账号&密码 等关键字段
    //     std::string id, passwd;
    //     GetValue(req, &id, &passwd);

    //     // 判断用户是否存在、密码是否正确
    //     if(Check(id, passwd) == true)
    //     {
    //         // 根据关键字段构建 session 对象
    //         Session* ss = new Session(id, passwd);

    //         // 根据 session 对象生成 session id
    //         int ssID = SessionMD5(ss);

    //         // 存储映射关系
    //         _sessions[ssID] = ss;

    //         // 返回 ssID
    //         return ssID;
    //     }

    //     return 0;
    // }

    // std::unordered_map<int, Session*> _sessions;

    // 根据请求对象，构建出响应对象
    bool LoadInfo(const Request& req)
    {
        _version = req._version;

        // 读取资源
        std::string path = req._path;
        if(Util::ReadFile(path, &_body) == false)
        {
            _st_code = "404";
            _st_msg = "No Found";
            path = webRoot + errPage_404;
            Util::ReadFile(path, &_body);
        }
        else
        {
            _st_code = "200";
            _st_msg = "OK";
        }

        // // 重新设置状态行（临时重定向）
        // _st_code = "301";
        // _st_msg = "Moved Permanently";

        // 设置报头
        _headers["Content-Length: "] = std::to_string(_body.size());
        _headers["Content-Type: "] = Util::GetSuffix(req._suffix);
        _headers["Set-Cookie: "] = "sessionID=12345668"; // 服务器设置 session id

        // _headers["Location: "] = "http://www.baidu.com"; 

        return true;
    }

    // 序列化
    bool Serialization(std::string* outStr)
    {
        outStr->clear();

        *outStr = _version + " " + _st_code + " " + _st_msg + SEP;

        for(auto &kv : _headers)
            *outStr += kv.first + kv.second + SEP;

        *outStr += SEP;

        *outStr += _body;

        return true;
    }

    ~Response()
    {}

public:
    std::string _version; // 协议版本
    std::string _st_code; // 状态码
    std::string _st_msg;  // 状态码信息
    std::unordered_map<std::string, std::string> _headers; // 响应报头
    std::string _body;    // 有效载荷
};